static void inline
free_shadow_l2_table(struct domain *d, unsigned long smfn)
{
- printk("free_shadow_l2_table(smfn=%p)\n", smfn);
-
unsigned long *pl2e = map_domain_mem(smfn << PAGE_SHIFT);
int i, external = shadow_mode_external(d);
unsigned long smfn;
unsigned long *guest, *shadow, *snapshot;
int need_flush = 0, external = shadow_mode_external(d);
+ int unshadow;
ASSERT(spin_is_locked(&d->arch.shadow_lock));
guest = map_domain_mem(entry->gmfn << PAGE_SHIFT);
snapshot = map_domain_mem(entry->snapshot_mfn << PAGE_SHIFT);
shadow = map_domain_mem(smfn << PAGE_SHIFT);
+ unshadow = 0;
switch ( stype ) {
case PGT_l1_shadow:
//
// snapshot[i] = new_pde;
}
+
+ // XXX - This hack works for linux guests.
+ // Need a better solution long term.
+ if ( !(new_pde & _PAGE_PRESENT) && unlikely(new_pde != 0) &&
+ (frame_table[smfn].u.inuse.type_info & PGT_pinned) &&
+ !unshadow )
+ {
+ perfc_incrc(unshadow_l2_count);
+ unshadow = 1;
+ }
}
break;
default:
unmap_domain_mem(shadow);
unmap_domain_mem(snapshot);
unmap_domain_mem(guest);
+
+ if ( unlikely(unshadow) )
+ shadow_unpin(smfn);
}
return need_flush;
struct domain *d = ed->domain;
unsigned long gmfn = pagetable_val(ed->arch.guest_table) >> PAGE_SHIFT;
unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
- unsigned long smfn, hl2mfn;
+ unsigned long smfn, hl2mfn, old_smfn;
int max_mode = ( shadow_mode_external(d) ? SHM_external
: shadow_mode_translate(d) ? SHM_translate
smfn = shadow_l2_table(d, gpfn, gmfn);
if ( !get_shadow_ref(smfn) )
BUG();
- if ( pagetable_val(ed->arch.shadow_table) )
- put_shadow_ref(pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT);
+ old_smfn = pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT;
ed->arch.shadow_table = mk_pagetable(smfn << PAGE_SHIFT);
+ if ( old_smfn )
+ put_shadow_ref(old_smfn);
SH_VVLOG("0: __update_pagetables(gmfn=%p, smfn=%p)", gmfn, smfn);
static int inline
validate_pde_change(
struct domain *d,
- unsigned long new_pde,
+ unsigned long new_gpde,
unsigned long *shadow_pde_p)
{
unsigned long old_spde, new_spde;
perfc_incrc(validate_pde_calls);
old_spde = *shadow_pde_p;
- l2pde_propagate_from_guest(d, &new_pde, &new_spde);
+ l2pde_propagate_from_guest(d, &new_gpde, &new_spde);
- // XXX Shouldn't we supposed to propagate the new_pde to the guest?
+ // XXX Shouldn't we propagate the new_gpde to the guest?
+ // And then mark the guest's L2 page as dirty?
- // only do the ref counting if something important changed.
+ // Only do the ref counting if something important changed.
//
if ( ((old_spde | new_spde) & _PAGE_PRESENT) &&
((old_spde ^ new_spde) & (PAGE_MASK | _PAGE_PRESENT)) )